package nancal.mp.mvc.devops


import io.swagger.annotations.Api
import io.swagger.annotations.ApiOperation
import nancal.mp.db.mongo.JenkinsLanguageEnum
import nancal.mp.db.mongo.entity.dev.*
import nancal.mp.db.mongo.mor
import nbcp.base.annotation.*
import nbcp.base.annotation.mvc.*
import nbcp.base.comm.*
import nbcp.base.db.IdCodeName
import nbcp.base.extend.*
import nbcp.base.json.*
import nbcp.mvc.sys.*
import nbcp.myoql.db.mongo.*
import nbcp.myoql.db.mongo.enums.MongoTypeEnum

import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import javax.servlet.http.HttpServletRequest

/**
 * Created by CodeGenerator at 2021-02-07 18:51:27
 */
@Api(description = "Git配置数据", tags = arrayOf("GitData"))
@RestController
@RequestMapping("/dev/git-data")
class GitDataAutoController {

    class GitDataModel() : GitData() {
        var productLineInfo = ProductLine()
    }

    enum class QueryOptionEnum {
        is80,
        not80,
        defaultDockerfile,
        notDefaultDockerfile,
        defaultYaml,
        notDefaultYaml;
    }

    @ApiOperation("列表")
    @PostMapping("/list-product-line")
    fun listProductLine(
        language: JenkinsLanguageEnum?,
    ): ListResult<IdCodeName> {
        //修复，当新加产品时，选择不到产品线的问题。
        if (language == null) {
            mor.dev.productLine.query()
                .select { it.code }
                .select { it.name }
                .toList()
                .apply {
                    return ListResult.of(this.map { IdCodeName(it.id, it.code, it.name) });
                }
        }

        var list = mor.dev.gitData.aggregate()
            .beginMatch()
            .where { it.language mongoEquals language }
            .endMatch()
            .groupWithId(
                "\$productLine.code",
                JsonMap(
                    "id2" to JsonMap("\$max" to "\$productLine._id"),
                    "code" to JsonMap("\$max" to "\$productLine.code"),
                    "name" to JsonMap("\$max" to "\$productLine.name")
                )
            )
            .toMapList()
            .map { IdCodeName(it.get("id2").AsString(), it.get("code").AsString(), it.get("name").AsString()) }

        return ListResult.of(list);
    }


    @ApiOperation("列表")
    @PostMapping("/list")
    fun list(
        id: String, //当列表列新一条后，刷新时使用
        gitServerId: String,
        language: JenkinsLanguageEnum?,
        name: String,
        languageVersion: String,
        productLineCode: String,
        appName: String,
        isLib: Boolean?,
        options: List<QueryOptionEnum>,
        @org.springframework.web.bind.annotation.RequestBody query: PagerModel<Any?>,
        request: HttpServletRequest
    ): ListResult<GitDataModel> {
        var myUserId = request.UserId;

        mor.dev.gitData.query()
            .apply {
                if (id.HasValue) {
                    this.where { it.id mongoEquals id }
                }

                if (gitServerId.HasValue) {
                    this.where { it.server.id mongoEquals gitServerId }
                }

                if (productLineCode.HasValue) {
                    this.where { it.productLine.code mongoEquals productLineCode }
                }

                if (language != null) {
                    this.where { it.language mongoEquals language }
                }

                if (isLib != null) {
                    this.where { it.isLib mongoEquals isLib }
                }

                if (languageVersion.HasValue) {
                    this.where { it.languageVersion mongoLike languageVersion }
                }

                if (name.HasValue) {
                    this.where { it.name mongoLike name }
                }

                if (appName.HasValue) {
                    this.where { it.folders.name mongoLike appName }
                }

                if (options.any()) {
                    if (options.intersect(
                            listOf(
                                QueryOptionEnum.is80,
                                QueryOptionEnum.not80
                            )
                        ).size == 1
                    ) {
                        if (options.contains(QueryOptionEnum.is80)) {
                            this.where { it.folders.port mongoIn arrayOf(0, 80) }
                        } else {
                            this.where { it.folders.port mongoNotIn arrayOf(0, 80) }
                        }
                    }

                    if (options.intersect(
                            listOf(
                                QueryOptionEnum.defaultDockerfile,
                                QueryOptionEnum.notDefaultDockerfile
                            )
                        ).size == 1
                    ) {
                        if (options.contains(QueryOptionEnum.defaultDockerfile)) {
                            this.where { it.folders.config.docker.id.mongoIsNullOrEmpty() }
                        } else {
                            this.where { it.folders.config.docker.id.mongoType(MongoTypeEnum.OBJECT_ID) }
                        }
                    }

                    if (options.intersect(
                            listOf(
                                QueryOptionEnum.defaultYaml,
                                QueryOptionEnum.notDefaultYaml
                            )
                        ).size == 1
                    ) {
                        if (options.contains(QueryOptionEnum.defaultYaml)) {
                            this.where { it.folders.config.k8sDeployment.id.mongoIsNullOrEmpty() }
                        } else {
                            this.where { it.folders.config.k8sDeployment.id.mongoType(MongoTypeEnum.OBJECT_ID) }
                        }
                    }
                }
            }
            .withPager(query)
            .orderByAsc { it.productLine.name }
            .toListResult(GitDataModel::class.java)
            .apply {
                val productLineCodes = this.data.map { it.productLine.code }.toSet();

                var productLines = mor.dev.productLine.query()
                    .where { it.code mongoIn productLineCodes }
                    .toList();
                this.data.forEach { gitData ->
                    gitData.productLineInfo =
                        productLines.firstOrNull { it.code == gitData.productLine.code }
                            ?: ProductLine()

                }
//                this.value = pl;
                return this;
            }
    }

    @ApiOperation("详情")
    @PostMapping("/detail/{id}")
    fun detail(
        @Require id: String,
        request: HttpServletRequest
    ): ApiResult<GitData> {
        mor.dev.gitData.queryById(id)
            .toEntity()
            .apply {
                if (this == null) {
                    return ApiResult.error<GitData>("找不到数据")
                }

                return ApiResult.of(this)
            }
    }

    @ApiOperation("更新")
    @PostMapping("/save")
    fun save(
        @org.springframework.web.bind.annotation.RequestBody entity: GitData,
        request: HttpServletRequest
    ): ApiResult<String> {
        //鉴权
        var userId = request.UserId;

        var productLine = mor.dev.productLine.queryByCode(entity.productLine.code).toEntity()!!
        entity.clusterCode = productLine.clusterCode;
        entity.productLine = IdCodeName(productLine.id, productLine.code, productLine.name)


        entity.folders.forEach {
            if (it.port == 0) {
                it.port = 80;
            }

            if (it.name.isNullOrEmpty()) {
                it.name = it.path
            }
        }

        checkUniqueAppName(entity);

        mor.dev.gitData.updateWithEntity(entity)
            .run {
                if (entity.id.HasValue) {
                    return@run this.execUpdate()
                } else {
                    return@run this.execInsert()
                }
            }
            .apply {
                if (this == 0) {
                    return ApiResult.error("更新失败")
                }

                return ApiResult.of(entity.id)
            }
    }

    private fun checkUniqueAppName(entity: GitData) {
        if (entity.isLib) {
            return;
        }

        entity.folders
            .map { it.name }
            .forEach { appName ->
                if (appName.contains("_")) {
                    throw RuntimeException("应用名不能有 下划线！")
                }

                if (appName.contains(" ")) {
                    throw RuntimeException("应用名不能有 空格！")
                }

                if (appName == "/" || appName.isNullOrEmpty()) {
                    return@forEach
                }

                var exists = mor.dev.gitData.query()
                    .apply {
                        if (entity.id.HasValue) {
                            this.where { it.id mongoNotEquals entity.id }
                        }
                    }
                    .where { it.folders.name mongoEquals appName }
                    .exists()


                if (exists) {
                    throw RuntimeException("系统中已存在 ${appName} ,不能重名！")
                }
            }
    }

    @ApiOperation("删除")
    @PostMapping("/delete/{id}")
    fun delete(
        @Require id: String,
        request: HttpServletRequest
    ): JsonResult {
        //鉴权
        var userId = request.UserId

        var entity = mor.dev.gitData.queryById(id).toEntity()
        if (entity == null) {
            return JsonResult.error("找不到数据")
        }

        mor.dev.gitData.deleteById(id)
            .exec()
            .apply {
                if (this == 0) {
                    return JsonResult.error("删除失败")
                }
                //实体上配置垃圾箱功能，可物理删除，会自动移到垃圾箱。
                return JsonResult()
            }
    }
}
